#!/bin/sh

#
# Source Control - Version 0.2.2b
#
# Author: Brad Cable
# Email: brad@bcable.net
# License: Modified BSD
# License Details:
# http://bcable.net/license.php
#

command="$1"
package="$2"
basedir="/var/srccontrol"
workingdir="$basedir/packages"
rbindir="$basedir/bin"
statdir="$basedir/status"

indentstr="     "


srccontrol_version="0.2.2b"

# Check for GAWK
if [ -z "`which gawk 2> /dev/null`" ]; then
	echo "GAWK is required to use SrcControl";
	exit
fi

# Package Manager Detection
pack_man="none"
[ ! -z "`which pkgtool 2> /dev/null | sed -r 's/^[^ ]+ not found$//g'`" ] && pack_man="tgz"
[ ! -z "`which dpkg 2> /dev/null | sed -r 's/^[^ ]+ not found$//g'`" ] && pack_man="deb"
[ ! -z "`which rpm 2> /dev/null | sed -r 's/^[^ ]+ not found$//g'`" ] && pack_man="rpm"

# Check for CheckInstall
checkinstall_exists=""
if [ ! -z "`which checkinstall 2> /dev/null`" ]; then
	checkinstall_exists=1
	ci_pkgstr=""
	case "$pack_man" in
		tgz) ci_pkgstr="S" ;;
		deb) ci_pkgstr="D" ;;
		rpm) ci_pkgstr="R" ;;
	esac
	[ -z "$ci_pkgstr" ] && checkinstall_exists=""
else
	echo "CheckInstall is highly recommended for use with SrcControl, but it is not required."
	echo "To obtain checkinstall:"
	echo "${indentstr}Debian/Ubuntu/Other Debian Derivatives: apt-get install checkinstall"
	echo "${indentstr}Slackware (assuming slackpkg installed): slackpkg install checkinstall"
	echo "${indentstr}Other Distros check http://asic-linux.com.mx/~izto/checkinstall/"
	read -n 1 -p "Do you wish to continue? " cont
	echo
	[ "$cont" != "y" ] && exit
fi

if [ -z "$command" ] || [ "$command" == "--help" ] || [ "$command" == "-help" ] || [ "$command" == "-h" ] || [ "$command" == "help" ]; then
	echo "SrcControl $srccontrol_version"
	echo "Author: Brad Cable"
	echo "License: GPL Version 2"
	echo
	echo "Commands for Manage Source Packages:"
	echo "${indentstr}srccontrol add <spg_file>         add a source package to the database"
	echo "${indentstr}srccontrol remove <pkgname>       remove  a source package from the database"
	echo "${indentstr}srccontrol create <pkgname>       create spg file from database entry"
	echo
	echo "Basic Commands:"
	echo "${indentstr}srccontrol update                 update all source package versions"
	echo "${indentstr}srccontrol list                   list all source packages"
	echo "${indentstr}srccontrol list-new               list all packages with new versions"
	echo "${indentstr}srccontrol upgrade-all            upgrade all packages with new versions"
	echo
	echo "Commands for Installed Source Packages:"
	echo "${indentstr}srccontrol update <pkgname>       update a specific source package's version"
	echo "${indentstr}srccontrol info <pkgname>         display information about a source package"
	echo "${indentstr}srccontrol install <pkgname>      install the source package"
	echo "${indentstr}srccontrol uninstall <pkgname>    uninstall the source package"
	echo "${indentstr}srccontrol reinstall <pkgname>    reinstall the source package"
	echo "${indentstr}srccontrol upgrade <pkgname>      upgrade the source package"
	echo "${indentstr}srccontrol stop <pkgname>         stop process for source package"
	echo "${indentstr}srccontrol start <pkgname>        start process for source package"
	echo "${indentstr}srccontrol restart <pkgname>      restart process for source package"
	exit
fi

# Setup Dirs
if [ "$UID" == "0" ]; then
	[ ! -d "$rbindir" ] && mkdir -p $rbindir
	[ ! -d "$workingdir" ] && mkdir -p $workingdir
	[ ! -d "$statdir" ] && mkdir -p $statdir
fi

if [ "$UID" != "0" ] && [ "$command" != "list" ] && [ "$command" != "list-new" ] && [ "$command" != "info" ]; then
	echo "You must be root to use this feature, only list, list-new, and info commands are available to normal users"
	exit
fi

theresponse=0
oumask=`umask`
umask 022

quit(){
	umask $oumask
	exit
}

gen_randchars(){
	alphabet="abcdefghijklmnopqrstuvwxyz"
	rndlets=""
	i=1
	while [ "$i" -le "8" ]; do
		let rndnum=$RANDOM%26
		rndlet="${alphabet:$rndnum:1}"
		let i+=1
		rndlets="$rndlets$rndlet"
	done
	echo "$rndlets"
}

file_ext(){
	file_extension=`echo $1 | sed -r 's/^.*\.([^\.]*)$/\1/g'`
	[ "$file_extension" == "$1" ] && return
	if [ "$file_extension" == "gz" ] || [ "$file_extension" == "bz2" ]; then
		file_extension2=`echo $1 | sed -r "s/^.*\.([^\.]*)\.$file_extension$/\1/g"`
		[ "$file_extension2" == "tar" ] && file_extension="tar.$file_extension"
	fi
	echo "$file_extension"
}

variable_parse(){
	ret="$1"
	ret="`variable_parse_onevar newver "$srcpkg_newver" "$ret"`"
	ret="`variable_parse_onevar progdir "$progdir" "$ret"`"
	ret="`variable_parse_onevar bindir "$bindir" "$ret"`"
	echo "$ret"
}

variable_parse_onevar(){
        var="$1"
        rep="$2"
        str="$3"
        replacement=`echo "$rep" | sed "s/\//\\\\\\\\\//g"`
	if [ "$str" != "`echo "$str" | sed -r "s/\{$var.*\}//g"`" ]; then
		value="`echo "$str" | gawk "{
			ORS=\\\"\\\"; OFS=\\\"\\\"
			l=length(\\\"$var\\\")

			str=\\\$0
			match(str,\\\"{$var[^}]*}\\\");
			matcher=RSTART
			while(matcher!=0){
				print substr(str,0,RSTART-1);
				if(RLENGTH-2-l>0){
					cmd=\\\"echo $replacement\\\"substr(str,RSTART+1+l,RLENGTH-2-l);
					system(cmd);
				}
				else print \\\"$replacement\\\"
				str=substr(str,RSTART+RLENGTH,length(str)-RSTART-RLENGTH+1)
				match(str,\\\"{$var[^}]*}\\\");
				matcher=RSTART
			}
			print str;

		}" 2> /dev/null | tr -d "\n"`"
		echo "$value"
	else echo "$str"; fi
}

get_info_attr(){
	attr=`cat $workingdir/$1/info 2> /dev/null | grep "^$2=" | sed 's/'$2'=//g'`
	echo "$attr"
}

set_info_attr(){
	filestrip=`cat $workingdir/$1/info 2> /dev/null | grep -v "^$2="`
	echo "$filestrip" > $workingdir/$1/info
	[ ! -z "$3" ] && echo "$2=$3" >> $workingdir/$1/info
}

get_status_attr(){
	attr=`cat $statdir/$1 2> /dev/null | grep "^$2=" | sed 's/'$2'=//g'`
	echo "$attr"
}

set_status_attr(){
	filestrip=`cat $statdir/$1 2> /dev/null | grep -v "^$2="`
	echo "$filestrip" > $statdir/$1
	echo "$2=$3" >> $statdir/$1
}

get_procname(){
	value="`echo \"$1\" | sed -r \"s/^.*\/([^\/]+)$/\1/g\"`"
	echo "$value"
}

get_curver(){
	curver_pkg="$1"
	[ -z "$curver_pkg" ] && curver_pkg="$package"
	up_cmd="`get_info_attr $curver_pkg curver_file`"
	if [ ! -z "`ls -d $up_cmd 2> /dev/null`" ]; then
		up_cmd="`echo \"$up_cmd\" | sed -r \"s/\//\\\\\\\\\//g\"`"
		curver_cmd="`get_info_attr $curver_pkg curver_command`"
		cmd=`echo "$curver_cmd" | sed -r "s/\{curver_file\}/$up_cmd/g"`
		errorhandle "$cmd" "" Error 2>&1
	else echo Error; fi
}

get_newver(){
	newver_pkg="$1"
	[ -z "$newver_pkg" ] && newver_pkg="$package"
	newver=`get_status_attr $newver_pkg srcpkg_newver`
	echo "$newver"
}

get_net_newver(){
	newver_page=`get_info_attr $1 newver_url`
	newver_page_regexp=`get_info_attr $1 newver_regexp`
	newver_parse=`get_info_attr $1 newver_parse`
	dl_file /tmp/$1.html "$newver_page" noprogbar
	if [ "${theresponse:0:2}" != "40" ]; then
		prog_line=`cat /tmp/$1.html | grep -Em 1 "$newver_page_regexp"`
		newver=`echo "$prog_line" | sed -r "s/^(.*?)$newver_page_regexp.*$/\2/g"`
		rm -f /tmp/$1.html
		if [ -z "$newver" ] || [ `echo $newver | wc -c` -ge "20" ]; then
			if [ "$2" == "0" ]; then newver=`get_net_newver $1 1`
			else echo "Error"; return; fi
		fi
		[ ! -z "$newver_parse" ] && newver=`eval "echo \"$newver\" | $newver_parse"`
		echo "$newver"
	else echo Error; fi
}

check_newver(){
	if [ -z "$1" ] && [ ! -z "$srcpkg_version" ]; then the_curver="$srcpkg_version"
	else the_curver=`get_curver $1`; fi
	the_newver=`get_newver $1`
	if [ "$the_newver" != "$the_curver" ] && [ "$the_newver" != "Error" ] && [ "$the_curver" != "Error" ] && [ ! -z "$the_newver" ]; then echo 1
	else echo 0; fi
}

get_newfile_append(){
	file_info=`wget $wget_opts --server-response --spider "$download_url" 2>&1`
	content_disp="`echo "$file_info" | grep "^  Content-Disposition" | sed -r "s/^.*filename=(.*)$/\1/g"`"
	if [ -z "$content_disp" ]; then check_file="$download_url"
	else check_file="$content_disp"; fi

	file_extension=`file_ext "$check_file"`
	[ -z "$file_extension" ] && echo "Error Determining Filetype: '$check_file'" && quit
	newfile_append="-$srcpkg_newver.$file_extension"
	echo $newfile_append
}

exec_file(){
	rndtmpfile="/tmp/srccontrol_`gen_randchars`"
	rm -f $rndtmpfile
	while read line; do
		variable_parse "$line" >> $rndtmpfile
	done < $1
	if [ "$2" == "install" ] && [ ! -z "$checkinstall_exists" ]; then checkinstall -$ci_pkgstr --default bash $rndtmpfile
	else bash $rndtmpfile; fi
	rm -f $rndtmpfile
}

errorhandle(){
	rndtmpfile="/tmp/srccontrol_`gen_randchars`"
	rm -f $rndtmpfile

	if [ -z "$2" ] && [ -z "$3" ]; then
		$1 2> $rndtmpfile
		[ -e "$rndtmpfile" ] && [ ! -z "`cat $rndtmpfile`" ] && cat $rndtmpfile && rm -f $rndtmpfile && return
	else
		return_val=`eval "$1" 2> $rndtmpfile`
		if [ ! -e "$rndtmpfile" ] || [ -z "`cat $rndtmpfile`" ]; then
			if [ ! -z "$2" ]; then echo "$2"
			else echo "$return_val"; fi
		else
			if [ ! -z "$3" ]; then echo "$3" 1>&2
			else echo "$return_val"; rm -f $rndtmpfile; quit; fi
		fi
	fi

	rm -f $rndtmpfile
}

check_deps(){
	deps="`get_info_attr $1 srcpkg_pkgdeps`"
	if [ ! -z "$deps" ]; then
		packs=""
		i=0
		while let i+=1 && [ "$i" -le `echo $deps | wc -w` ] && dep=`echo $deps | awk '{print $'$i'}'`; do

			if [ "$dep" == "`echo $dep | sed 's/\://g'`" ]; then
				pack="$dep"
				file="$dep"
			else
				pack=`echo $dep | cut -d ':' -f1`
				file=`echo $dep | cut -d ':' -f2`
			fi

			curver=`get_curver $pack`

			success=0
			if [ ! -z "$curver" ] && [ "$curver" != "Error" ]; then success=1
			else [ ! -z "`which $file 2> /dev/null`" ] || [ ! -z "`ls $file 2> /dev/null`" ] && success=1; fi

			if [ "$success" != "1" ]; then
				if [ "$2" == "noquit" ]; then packs="$packs $pack"
				else echo "Error: Source Package '$1' requires '$pack' to run correctly."; quit; fi
			fi
		done
		[ ! -z "$packs" ] && echo $packs
	fi
}

do_deps(){
	deps=`check_deps $1 noquit`
	if [ ! -z "$deps" ]; then
		quit_later=""
		for dep in "$deps"; do
			if [ -e "$workingdir/$dep/info" ]; then command install $dep indent; echo
			else
				echo "Error: Source Package '$1' requires '$dep' to run correctly."
				quit_later=1
			fi
		done
		[ ! -z "$quit_later" ] && quit
		echo
		echo "Dependencies Resolved, continuing with setup."
		echo
	fi
}

do_forces(){
	finst=`get_info_attr $1 srcpkg_forceinstall`
	if [ ! -z "$finst" ]; then
		echo
		echo "Source Package '$1' has forces, resolving..."
		echo
		for forc in "$finst"; do
			if [ -e "$workingdir/$finst/info" ]; then command reinstall $forc indent; echo
			else echo "Error: Source Package '$1' forces '$forc' to reinstall, which could not be found."; fi
		done
		echo "Forces Resolved."
		echo
	fi
}

hr_bytes(){
	let "bytecount=$1*10"
	suffix="$2"
	chars="$3"
	[ -z "$3" ] && chars=" KMGT"

	i=0
	while [ "$bytecount" -ge "10240" ] && [ "$i" -le "3" ]; do
		let "bytecount=$bytecount/1024"
		let "i+=1"
	done

	bytecount1="${bytecount:0:${#bytecount}-1}"
	bytecount2="${bytecount:${#bytecount}-1:1}"
	if [ -z "$bytecount1" ]; then bytecount1="0"; fi

	if [ -z "$4" ]; then spacer=" "
	else spacer=""; fi

	echo $bytecount1.$bytecount2$spacer${chars:$i:1}$suffix
}

file_size(){
	size=`stat "$1" 2> /tmp/file_size_error | grep ^\ \ Size\: | cut -d ' ' -f4`
	if [ -z "`cat /tmp/file_size_error`" ]; then echo "$size"
	else echo 0; fi
	rm -f /tmp/file_size_error
}

cd_to_extracted_fol(){
	returnval=`cd "$workdir" 2>&1`
	[ ! -z "$returnval" ] && return
	cd "$workdir"
	fol=`ls`
	if [ -d "$fol" ]; then cd $fol
	else cd *${srcpkg_newver}*/ &> /dev/null; fi
}

dl_file(){

	dfile="$2"
	ofile="$1"

	if [ "$3" == "noprogbar" ]; then
		theresponse=`wget $wget_opts -O "$ofile" "$dfile" 2>&1 | grep ^HTTP | grep -vE " 30[0-9] " | cut -d '.' -f4 | cut -d ' ' -f2-4`
		return
	fi

	file_info=`wget $wget_opts --server-response --spider "$dfile" 2>&1`
	theresponse=`echo "$file_info" | grep "^  HTTP" | cut -d ' ' -f4`

	if [ "${theresponse:0:2}" != "40" ]; then

		total_bytes=`echo "$file_info" | grep ^Length | cut -d ' ' -f2 | sed 's/,//g'`

		if [ ! -z "$total_bytes" ] && [ "$total_bytes" != "0" ] && [ "$total_bytes" != "unspecified" ]; then

			#tput civis
			echo 1>&2

			fdate=`date +%s%N`

			if [ -z "$mirror_no" ] || [ -z "$env_mirrors" ]; then lefttext1="  Progress: "
			else lefttext1="  Mirror ($mirror_no/$env_mirrors): "; fi

			lefttext2="%  ["
			righttext="]"

			wget $wget_opts -O "$ofile" "$dfile" &> /dev/null &

			cur_size="0"
			pcent="0"
			while [ ! -z "`ps aux | grep \"wget $wget_opts -O $ofile\" | grep -v grep`" ] || [ "$pcent" != "101" ]; do

				totcols=`tput cols`
				progcols="$totcols"
				let "progcols-=${#lefttext1}+${#lefttext2}+3+${#righttext}+13"
				let "progcomp=$progcols+1"

				let "rightstart=$totcols-${#righttext1}-${#righttext}-13"

				let "pcent=$cur_size*100/$total_bytes"
				let "progbar_cnt=$pcent*$progcols/100"

				progbar_chars=""
				while [ "${#progbar_chars}" -le "$progbar_cnt" ]; do progbar_chars="$progbar_chars="; done
				[ "${#progbar_chars}" != "$progcols" ] && [ "$pcent" != "100" ] && progbar_chars="$progbar_chars>"
				while [ "${#progbar_chars}" -le "$progcomp" ]; do progbar_chars="$progbar_chars "; done

				while [ "${#pcent}" -le "2" ]; do pcent=" $pcent"; done

				cdate=`date +%s%N`
				let "kb=($cur_size*1000000000)/($cdate-$fdate)"
				kbsec=`hr_bytes "$kb" "/s  " BKMGT`

				let "kbspaces=10-${#kbsec}"

				kb_chars=""
				while [ "${#kb_chars}" -le "$kbspaces" ]; do kb_chars=" $kb_chars"; done

				echo -n "$lefttext1$pcent$lefttext2$progbar_chars" 1>&2
				tput cr

				tput cuf $rightstart
				echo -n "$righttext$kb_chars$kbsec" 1>&2
				tput cr

				sleep 0.5
				cur_size=`file_size "$ofile"`

				[ "$pcent" == "100" ] && pcent="101"

			done

			tput dl 1
			tput cuu 1

			#tput cnorm

		else wget $wget_opts -O "$ofile" "$dfile" &> /dev/null; echo 1>&2; tput cr; tput cuu 1; fi

	fi

}

env_vars(){

	command="$1"
	package="$2"
	progdir="$workingdir/$package"
	bindir="$rbindir/$package"
	workdir="$bindir/work"

	wget_opts="--timeout=20 --tries=2"

	noshowcur=0
	indent=0
	noerror=0
	force=0

	extras=""

	i=1
	for extra in "$@"; do
		if [ "$i" -le "2" ]; then
			let i++
			continue
		fi

		add=1
		case "$extra" in
			noshowcur) noshowcur=1 ;;
			indent) indent=1 ;;
			noerror) noerror=1 ;;
			force) force=1 ;;
			*) add=0 ;;
		esac
		[ "$add" == "1" ] && extras="$extras $extra"

	done

	srcpkg_name="`get_info_attr $package srcpkg_name`"
	srcpkg_creator="`get_info_attr $package srcpkg_creator`"
	srcpkg_pkgdeps="`get_info_attr $package srcpkg_pkgdeps`"

	newver_url="`get_info_attr $package newver_url`"
	newver_regexp="`get_info_attr $package newver_regexp`"

	download_url="`get_info_attr $package download_url`"
	download_mirror1="`get_info_attr $package download_mirror1`"
	if [ ! -z "$download_mirror1" ]; then
		i=1
		new_download_mirror="$download_mirror1"
		while [ ! -z "$new_download_mirror" ]; do
			eval "download_mirror$i=\"$new_download_mirror\""
			let i+=1
			new_download_mirror="`get_info_attr $package download_mirror$i`"
		done
		env_mirrors="$i"
	fi

	wget_nouseragent="`get_info_attr $package wget_nouseragent | tr A-Z a-z`"
	referer="`get_info_attr $package wget_referer | cut -d ' ' -f1`"
	[ ! -z "$referer" ] && wget_opts="$wget_opts --referer=$referer"
	[ "$wget_nouseragent" == "true" ] && wget_opts="$wget_opts -U \"\""

	curver_file="`get_info_attr $package curver_file`"

	env_bindir="`get_info_attr $package env_bindir`"
	[ ! -z "$env_bindir" ] && bindir="$env_bindir"

	env_workdir="`get_info_attr $package env_workdir`"
	[ ! -z "$env_workdir" ] && workdir=`variable_parse "$env_workdir"`

	opt_noextract="`get_info_attr $package opt_noextract | tr A-Z a-z`"
	opt_noconfigure="`get_info_attr $package opt_noconfigure | tr A-Z a-z`"
	opt_nocompile="`get_info_attr $package opt_nocompile | tr A-Z a-z`"
	opt_nocleanup="`get_info_attr $package opt_nocleanup | tr A-Z a-z`"

	extract_command="`get_info_attr $package extract_command`"

	srcpkg_procname="`get_info_attr $package srcpkg_procname`"
	[ -z "$srcpkg_procname" ] && srcpkg_procname="`get_procname \"$curver_file\"`"

	srcpkg_version="`get_curver`"
	srcpkg_newver="`get_newver`"

	srcpkg_usefileext="`get_info_attr $package srcpkg_usefileext`"
	binfile="`ls $bindir/ 2> /dev/null | grep -v work`"
	binfileext=`file_ext "$binfile"`
	[ ! -z "$srcpkg_usefileext" ] && binfileext="$srcpkg_usefileext"

}

## Command Line Parsing & Handling ##
command(){

	#command="$1"
	#package="$2"

	env_vars $@

	# check if 'info' file exists, and get variables from it 
	if [ ! -e "$progdir/info" ] && [ "$command" != "add" ]; then
		echo $package
		echo Error: Source Package Not Found
		return
	fi

	case "$command" in

		add)
			echo -n "Adding Source Package: "
			errorhandle "tar jxvf $package -C $workingdir" Done Error
			;;

		remove)
			read -n 1 -p "Are you sure you wish to remove package '$package'? " key
			if [ "$key" == "y" ] || [ "$key" == "Y" ]; then
				echo
				echo -n "Removing Source Package: "
				rm -rf $workingdir/$package
				echo Done
			else echo "Aborted"; fi
			;;

		create)
			date=`stat $progdir/info | grep "^Modify\: " | cut -d ' ' -f2 | sed 's/\-//g'`
			echo -n "Creating Source Package: "
			filename="$package-$date-$srcpkg_creator.spg"
			pwd=`pwd`
			cd $workingdir
			errorhandle "tar jcvf $pwd/$filename $package;chmod 644 $pwd/$filename" Done Error
			;;

		info | update)
			[ "$srcpkg_version" == "$srcpkg_newver" ] && [ "$noshowcur" == "1" ] && return

			[ -z "$srcpkg_version" ] || [ "$srcpkg_version" == "Error" ] && srcpkg_version="Not Installed"
			echo -n "$srcpkg_name $srcpkg_version "
		
			if [ "$command" == "update" ] || [ -z "$srcpkg_newver" ]; then
				net_newver=`get_net_newver $package`
				if [ "$net_newver" != "Error" ]; then
					srcpkg_newver="$net_newver"
					set_status_attr $package srcpkg_newver "$srcpkg_newver"
				else echo "(Error Updating Version, Cached Newest Version: $srcpkg_newver)"; set_status_attr $package error 1; return; fi
			fi

			if [ "$srcpkg_version" == "$srcpkg_newver" ]; then echo -n "(up to date)"
			else echo -n "(newest: $srcpkg_newver)"; fi

			lock=`get_status_attr $package lock`
			if [ "$lock" == "lock" ]; then echo "  *locked*"
			else echo; fi

			;;

		version) get_curver ;;

		download)
			[ "$indent" == "1" ] && echo -n "$indentstr"
			command info $package
			echostr="Downloading $package-$srcpkg_newver: "
			echo -n "$echostr"
			echosize="${#echostr}"

			mirror_no=""
			if [ ! -z "$download_mirror1" ]; then
				mirror_no=$RANDOM
				let "mirror_no%=$env_mirrors"
				let mirror_no+=1
				eval "the_download=\"\$download_mirror$mirror_no\""
			else the_download="$download_url"; fi

			download_file=`variable_parse "$the_download"`
			newfile="$package"`get_newfile_append`

			if [ -e "$bindir/$newfile" ]; then
				echo "File Exists, Skipping"
				return
			else rm -rf $bindir; fi
			mkdir -p $bindir

			dl_file /tmp/$newfile "$download_file"
			tput cuf $echosize

			if [ "${theresponse:0:2}" == "40" ]; then
				echo $theresponse 1>&2
				quit
			fi

			dus=`du -s /tmp/$newfile 2> /dev/null`

			if [ ! -e "/tmp/$newfile" ] || [ "${dus:0:1}" == "0" ]; then
				rm -rf /tmp/$newfile
				echo Error 1>&2
			else mv /tmp/$newfile $bindir; echo Done; fi
			;;

		extract)
			[ "$opt_noextract" == "true" ] && return
			newfile="$package"`get_newfile_append`
			[ "$indent" == "1" ] && echo -n "$indentstr"
			echo -n "Extracting $newfile: "
			[ ! -e "$bindir/$newfile" ] && echo "File Not Found"

			if [ "$opt_nocleanup" != "true" ]; then
				[ -d "$workdir" ] && rm -rf $workdir
				mkdir -p $workdir
			fi

			cd $workdir
			if [ -z "$extract_command" ]; then
				case "$binfileext" in
					tar) extract_command="tar xvf" ;;
					tar.gz) extract_command="tar zxvf" ;;
					tar.bz2) extract_command="tar jxvf" ;;
					gz) extract_command="gunzip" ;;
					bz2) extract_command="bunzip2" ;;
					zip) extract_command="unzip" ;;
					rar) extract_command="rar x" ;;
					tgz)
						case "$pack_man" in
							tgz) extract_command=":" ;;
							deb) extract_command="alien" ;;
							*) echo "Error, no recognized package manager to handle TGZ format, need Slackware's 'pkgtool' or Debian's 'dpkg' to continue..." 1>&2; quit ;;
						esac
						;;
					deb)
						case "$pack_man" in
							deb) extract_command=":" ;;
							*) echo "Error, no recognized package manager to handle TGZ format, need Debian's 'dpkg' to continue..." 1>&2; quit ;;
						esac
						;;
					rpm)
						case "$pack_man" in
							tgz) extract_command="rpm2tgz" ;;
							deb) extract_command="alien" ;;
							rpm) extract_command=":" ;;
							*) echo "Error, no recognized package manager to handle RPM format, need Slackware's 'pkgtool', Debian's 'dpkg', or RedHat's 'rpm' to continue..." 1>&2; quit ;;
						esac
						;;
					*) echo "Error, no default extract command for file extension '$binfileext'..." 1>&2; quit ;;
				esac
			fi
			$extract_command $bindir/$newfile &> /dev/null
			if [ ! -z "`ls`" ]; then echo Done
			else echo Error 1>&2; quit; fi
			;;

		configure)
			[ ! -e "$progdir/configure" ] && case "$binfileext" in "tgz" | "deb" | "rpm") return ;; esac
			[ "$opt_noconfigure" == "true" ] && return
			[ "$indent" == "1" ] && echo -n "$indentstr"
			echo -n "Configuring $package-$srcpkg_newver: "
			[ ! -d "$workdir" ] && echo "Working Directory Not Found" && quit
			cd_to_extracted_fol
			if [ ! -e "$progdir/configure" ]; then ./configure --prefix=/usr &> /dev/null
			else exec_file "$progdir/configure" &> /dev/null; fi
			echo Done
			;;

		compile)
			[ ! -e "$progdir/compile" ] && case "$binfileext" in "tgz" | "deb" | "rpm") return ;; esac
			[ "$opt_nocompile" == "true" ] && return
			[ "$indent" == "1" ] && echo -n "$indentstr"
			echo -n "Compiling $package-$srcpkg_newver: "
			[ ! -d "$workdir" ] && echo "Working Directory Not Found" && quit
			cd_to_extracted_fol
			if [ ! -e "$progdir/compile" ]; then make &> /dev/null
			else exec_file $progdir/compile &> /dev/null; fi
			echo Done
			;;

		installsrc)
			[ "$indent" == "1" ] && echo -n "$indentstr"
			echo -n "Installing $package-$srcpkg_newver: "
			[ ! -z "$extract_command" ] && [ ! -d "$workdir" ] && echo "Working Directory Not Found" && quit
			cd_to_extracted_fol

			if [ ! -e "$progdir/install" ]; then
				case "$binfileext" in
					tgz | deb | rpm)
						case "$pack_man" in
							tgz) hdl_cmd="installpkg $binfile" ;;
							deb) hdl_cmd="dpkg -i $binfile" ;;
							rpm) hdl_cmd="rpm -i $binfile" ;;
						esac
						;;
					*)
						case "$pack_man" in
							tgz | deb | rpm) hdl_cmd="checkinstall -$ci_pkgstr --default" ;;
							*) hdl_cmd="make install" ;;
						esac
						;;
				esac
			else hdl_cmd="exec_file $progdir/install install"; fi
			errorhandle "$hdl_cmd" Done Error
			;;

		uninstall)
			if [ -z "$srcpkg_version" ]; then
				[ "$noerror" != "1" ] && echo "Error: $srcpkg_name is not installed, cannot perform uninstall."
				return
			fi
			[ "$indent" == "1" ] && echo -n "$indentstr"
			echo -n "Uninstalling $package-$srcpkg_version: "
			if [ ! -e "$progdir/uninstall" ]; then
				case "$pack_man" in
					tgz) hdl_cmd="removepkg $package" ;;
					deb) hdl_cmd="dpkg -r $package" ;;
					rpm) hdl_cmd="rpm -r $package" ;;
					*) echo "Error, default package manager not detected, could not uninstall" 1>&2; quit ;;
				esac
			else hdl_cmd="exec_file $progdir/uninstall"; fi
			errorhandle "$hdl_cmd" Done Error
			;;

		cleanup)
			[ "$opt_nocleanup" == "true" ] && return
			[ "$indent" == "1" ] && echo -n "$indentstr"
			echo -n "Cleaning Up: "
			rm -rf $workdir
			echo Done
			;;

		install)
			[ ! -z "$srcpkg_version" ] && [ "$srcpkg_version" != "Error" ] && echo "Error: $srcpkg_name is already installed, please use 'reinstall' if you wish to reinstall this program." && quit
			do_deps $package
			env_vars $@
			command download $package $extras
			command extract $package $extras
			command configure $package $extras
			command compile $package $extras
			command installsrc $package $extras
			command cleanup $package $extras
			do_forces $package
			;;

		reinstall | upgrade)
			if [ "$command" == "upgrade" ] && [ "`check_newver`" == "0" ] && [ "$force" != "1" ]; then
				[ "$noerror" != "1" ] && echo "Error: $srcpkg_name is up to date."
				return
			fi
			do_deps $package
			env_vars $@
			command download $package $extras
			command extract $package $extras
			command configure $package $extras
			command compile $package $extras
			command uninstall $package $extras
			command installsrc $package $extras
			command cleanup $package $extras
			do_forces $package
			;;

		stop)
			[ "$indent" == "1" ] && echo -n "$indentstr"
			echo -n "Stopping $srcpkg_name $srcpkg_version: "
			if [ ! -e "$progdir/stop" ]; then errorhandle "exec_file $progdir/stop" Stopped Error
			else
				pgrep=`pgrep $srcpkg_procname`
				[ -z "$pgrep" ] && echo "PID Not Found" && quit
				killall $srcpkg_procname
			fi
			echo Stopped
			;;

		start)
			[ ! -e "$progdir/start" ] && break
			[ "$indent" == "1" ] && echo -n "$indentstr"
			echo -n "Starting $srcpkg_name $srcpkg_version: "
			errorhandle "exec_file $progdir/start" Started Error
			#pgrep=`pgrep $srcpkg_procname`
			#if [ -z "$pgrep" ]; then echo "Error: Could not start $srcpkg_name."; quit
			;;

		restart)
			command stop $package $extras
			command start $package $extras
			;;

		lock)
			set_status_attr $package lock lock
			echo "$srcpkg_name locked from upgrading through 'srccontrol upgrade-all'."
			;;

		unlock)
			set_status_attr $package lock ""
			echo "$srcpkg_name unlocked."
			;;

		*)
			echo "Error: Command Not Recognized"
	esac

}

if [ -z "$package" ]; then
	noquit=0
	case "$command" in

		update)
			echo
			totalpkgs=0
			newpkgs=0
			errorpkgs=0
			for pkg in `ls $workingdir`; do
				[ ! -e "$workingdir/$pkg/info" ] && continue
				let totalpkgs++
				command update $pkg
				newver=`get_newver $pkg`
				curver=`get_curver $pkg`
				[ "$newver" != "$curver" ] && let newpkgs++
				[ "$newver" == "Error" ] && echo "Error getting new version for '$pkg'" && let errorpkgs++ && continue
				[ ! -z "`get_status_attr $pkg error`" ] && set_status_attr $pkg error "" && let errorpkgs++ && continue
			done
			echo
			echo Total Packages: $totalpkgs \| New Packages: $newpkgs
			echo Errorneous Packages: $errorpkgs
			echo
			;;

		list)
			echo
			totalpkgs=0
			newpkgs=0
			errorpkgs=0
			for pkg in `ls $workingdir`; do
				[ ! -e "$workingdir/$pkg/info" ] && continue
				let totalpkgs++
				command info $pkg
				newver=`get_newver $pkg`
				curver=`get_curver $pkg`
				[ "$newver" != "$curver" ] && let newpkgs++
				[ "$newver" == "Error" ] && echo "Error getting new version for '$pkg'" && let errorpkgs++ && continue
				[ ! -z "`get_status_attr $pkg error`" ] && set_status_attr $pkg error "" && let errorpkgs++ && continue
			done
			echo
			echo Total Packages: $totalpkgs \| New Packages: $newpkgs
			echo Errorneous Packages: $errorpkgs
			echo
			;;

		list-new)
			echo
			totalpkgs=0
			newpkgs=0
			errorpkgs=0
			for pkg in `ls $workingdir`; do
				[ ! -e "$workingdir/$pkg/info" ] && continue
				let totalpkgs++
				command info $pkg noshowcur
				newver=`get_newver $pkg`
				curver=`get_curver $pkg`
				[ "$newver" != "$curver" ] && let newpkgs++
				[ "$newver" == "Error" ] && echo "Error getting new version for '$pkg'" && let errorpkgs++ && continue
				[ "$curver" == "Error" ] && echo "Error getting current version for '$pkg'" && let errorpkgs++ && continue
				[ ! -z "`get_status_attr $pkg error`" ] && set_status_attr $pkg error "" && let errorpkgs++ && continue
			done
			[ "$newpkgs" != "0" ] && echo
			echo Total Packages: $totalpkgs \| New Packages: $newpkgs
			echo Errorneous Packages: $errorpkgs
			echo
			;;

		upgrade-all)
			echo
			newpkgs=0
			for pkg in `ls $workingdir`; do
				lock=`get_status_attr $pkg lock`
				[ "$lock" == "lock" ] && continue
				[ ! -e "$workingdir/$pkg/info" ] && continue
				if [ "`check_newver $pkg`" == "1" ]; then
					command upgrade $pkg indent noerror
					let newpkgs++
				fi
			done
			[ "$newpkgs" != "0" ] && echo
			echo Source Packages Upgraded: $newpkgs
			echo
			;;

		version) echo $srccontrol_version ;;

	esac
	[ "$noquit" == "0" ] && quit

else command $command $package; fi
